﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapWindow;
using System.Windows.Forms;
using MapWindow.Data;
using Point = System.Drawing.Point;
using System.Data;


namespace SkiPathStandalone
{
    public class ProfileCreator
    {
        private List<Point> points = new List<Point>();
        public static DataTable table = new DataTable();
        /// <summary>
        /// Extract Elevaton
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="endX"></param>
        /// <param name="endY"></param>
        /// <param name="demGrid"></param>
        /// <param name="table"></param>
        private void FactorCalulator(double startX, double startY, double endX, double endY,
                                      Raster demGrid, DataTable table)
        {
            //get the cell size of the dem Grid
            double cellX = demGrid.CellWidth; ;
            double cellY = demGrid.CellHeight;

            RcIndex startIndex = new RcIndex();
            startIndex = demGrid.ProjToCell(startX, startY);
            RcIndex endIndex = new RcIndex();
            endIndex = demGrid.ProjToCell(endX, endY);

            int startRow = startIndex.Row;
            int endRow = endIndex.Row;
            int startCol = startIndex.Column;
            int endCol = endIndex.Column;
            int curRow;
            int curCol;
            double curDist = 0;
            //Get the Height difference
            //we assume the number of points in the segment is 100 points
            Int32 numberOfPoints = 4;

            //declare arrays for storing distance, elevation, slope
            double[] distanceArray = new double[numberOfPoints - 1];
            double[] elevationArray = new double[numberOfPoints - 1];
            double[] slopeArray = new double[numberOfPoints - 1];

            double constXDif = (endCol - startCol) / numberOfPoints;
            double constYDif = (endRow - startRow) / numberOfPoints;
            double constDiagDif = Math.Sqrt(Math.Pow(constXDif, 2.0) + Math.Pow(constYDif, 2.0));
            curCol = startCol;
            curRow = startRow;
            distanceArray[0] = curDist;
            elevationArray[0] = Convert.ToDouble(demGrid.Value[curRow, curCol]);
            for (int j = 1; j < numberOfPoints - 1; j++)
            {
                curCol = curCol + Convert.ToInt32(constXDif);
                curRow = curRow + Convert.ToInt32(constYDif);
                curDist = curDist + constDiagDif;
                distanceArray[j] = curDist;
                elevationArray[j] = Convert.ToDouble(demGrid.Value[curRow, curCol]);
            }
            //find the slope
            for (int k = 0; k < distanceArray.Length; k++)
            {
                if (k == distanceArray.Length - 1)
                {
                    slopeArray[k] = slopeArray[k - 1];
                    break;
                }
                double elevationDif = Math.Abs(elevationArray[k] - elevationArray[k + 1]);
                double slope = elevationDif / constDiagDif;
                slopeArray[k] = slope;
            }

            //Assign the data to a table for display
            if (table.Rows.Count == 0)
            {
                for (int i = 0; i < elevationArray.Length; i++)
                {
                    DataRow tableRow = table.NewRow();
                    tableRow[0] = distanceArray[i];
                    tableRow[1] = elevationArray[i];
                    tableRow[2] = slopeArray[i];
                    table.Rows.Add(tableRow);
                }
            }
            else
            {
                double initialDistance = Convert.ToDouble(table.Rows[table.Rows.Count - 1].ItemArray[0].ToString());
                for (int i = 1; i < elevationArray.Length; i++)
                {
                    DataRow tableRow = table.NewRow();
                    tableRow[0] = distanceArray[i] + initialDistance;
                    tableRow[1] = elevationArray[i];
                    tableRow[2] = slopeArray[i];
                    table.Rows.Add(tableRow);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="DEMFilename"></param>
        /// <param name="Shapefilename"></param>
        public void GenerateProfile(Raster DEMFile, FeatureSet Shapefile)
        {

            if (Shapefile.Features.Count == 0)
            {
                MessageBox.Show("Please select a shapefile for ski path.");
            }
            else
            {
                for (int i = 0; i < Shapefile.Vertex.Length; i++)
                {
                    Point myPoint = new Point();
                    myPoint.X = Convert.ToInt32(Shapefile.Vertex[i]);
                    myPoint.Y = Convert.ToInt32(Shapefile.Vertex[i + 1]);
                    points.Add(myPoint);
                    i++;
                }
                table.Columns.Add(new DataColumn("distance"));
                table.Columns.Add(new DataColumn("elevation"));
                table.Columns.Add(new DataColumn("slope"));
                for (int i = 0; i < points.Count; i++)
                {
                    if (i == points.Count - 1) break;
                    FactorCalulator(points[i].X, points[i].Y,
                        points[i + 1].X, points[i + 1].Y, DEMFile, table);
                }
                // Setup the graph
                frmProfile frm = new frmProfile();
                frm.Show();

            }
        }

    }

}
